package com.springup.trade.service.impl;

import com.springup.trade.entity.Transaction;
import com.springup.trade.exception.Error;
import com.springup.trade.exception.RequestException;
import com.springup.trade.item.Operate;
import com.springup.trade.item.Transact;
import com.springup.trade.mapper.TransactionMapper;
import com.springup.trade.service.TransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Brin
 * @date 20200623
 * @description security transact service
 */
@Service
public class TransactionServiceImpl implements TransactionService {
    private static Lock lock = new ReentrantLock();

    /**
     * input buy
     * @param transaction
     * @return
     */
    @Override
    public Transaction inputBuy(Transaction transaction) {
        lock.lock();
        try{
            transaction.setOperateType(Operate.INSERT.getId());
            transaction.setTransactType(Transact.BUY.getId());
            transaction.setVersion(1);
            int count = transactionMapper.queryCount(transaction);
            if(count == 0){
                transaction.setTradeId(1);
            }else{
                Transaction temp = transactionMapper.queryTransaction(transaction);
                if(temp == null){
                    transaction.setTradeId(1);
                }else{
                    transaction.setTradeId(temp.getTradeId());
                }
            }
            transactionMapper.insert(transaction);
            return transactionMapper.queryTransactionByTransactionId(transaction);
        }catch (Exception e){
            throw new RequestException(400, e.getMessage());
        }finally {
            lock.unlock();
        }
    }

    /**
     * update buy
     * @param transaction
     * @return
     */
    @Override
    public Transaction updateBuy(Transaction transaction) {
        lock.lock();
        try{
            transaction.setOperateType(Operate.UPDATE.getId());
            transaction.setTransactType(Transact.BUY.getId());
            Transaction temp = transactionMapper.queryTransaction(transaction);
            if(temp == null){
                throw new RequestException(Error.BUY_UPDATE_ERROR.getId(), Error.BUY_UPDATE_ERROR.getName());
            }
            transaction.setVersion(temp.getVersion() + 1);
            transaction.setTradeId(temp.getTradeId());
            transactionMapper.insert(transaction);
            transaction = transactionMapper.queryTransactionByTransactionId(transaction);
        }catch (Exception e){
            throw new RequestException(400, e.getMessage());
        }finally {
            lock.unlock();
        }
        return transaction;
    }

    /**
     * cancel buy
     * @param transaction
     * @return
     */
    @Override
    public Transaction cancelBuy(Transaction transaction) {
        lock.lock();
        try{
            transaction.setOperateType(Operate.CANCEL.getId());
            transaction.setTransactType(Transact.BUY.getId());
            Transaction temp = transactionMapper.queryTransaction(transaction);
            if(temp == null){
                throw new RequestException(Error.BUY_CANCEL_ERROR.getId(), Error.BUY_CANCEL_ERROR.getName());
            }
            transaction.setVersion(temp.getVersion() + 1);
            transaction.setTradeId(temp.getTradeId());
            transactionMapper.insert(transaction);
            transaction = transactionMapper.queryTransactionByTransactionId(transaction);
        }catch (Exception e){
            throw new RequestException(400, e.getMessage());
        }finally {
            lock.unlock();
        }
        return transaction;
    }


    /**
     * insert sell
     * @param transaction
     * @return
     */
    @Override
    public Transaction outputSell(Transaction transaction) {
        lock.lock();
        try{
            transaction.setOperateType(Operate.INSERT.getId());
            transaction.setTransactType(Transact.SELL.getId());
            transaction.setVersion(1);
            int count = transactionMapper.queryCount(transaction);
            if(count == 0){
                transaction.setTradeId(1);
            }else{
                Transaction temp = transactionMapper.queryTransaction(transaction);
                if(temp == null){
                    transaction.setTradeId(1);
                }else{
                    transaction.setTradeId(temp.getTradeId());
                }
            }
            transactionMapper.insert(transaction);
            return transactionMapper.queryTransactionByTransactionId(transaction);
        }catch (Exception e){
            throw new RequestException(400, e.getMessage());
        }finally {
            lock.unlock();
        }
    }

    @Override
    public Transaction updateSell(Transaction transaction) {
        lock.lock();
        try{
            transaction.setOperateType(Operate.UPDATE.getId());
            transaction.setTransactType(Transact.SELL.getId());
            Transaction temp = transactionMapper.queryTransaction(transaction);
            if(temp == null){
                throw new RequestException(Error.SELL_UPDATE_ERROR.getId(), Error.SELL_UPDATE_ERROR.getName());
            }
            transaction.setVersion(temp.getVersion() + 1);
            transaction.setTradeId(temp.getTradeId());
            transactionMapper.insert(transaction);
            transaction = transactionMapper.queryTransactionByTransactionId(transaction);
        }catch (Exception e){
            throw new RequestException(400, e.getMessage());
        }finally {
            lock.unlock();
        }
        return transaction;
    }

    @Override
    public Transaction cancelSell(Transaction transaction) {
        lock.lock();
        try{
            transaction.setOperateType(Operate.CANCEL.getId());
            transaction.setTransactType(Transact.SELL.getId());
            Transaction temp = transactionMapper.queryTransaction(transaction);
            if(temp == null){
                throw new RequestException(Error.SELL_CANCEL_ERROR.getId(), Error.SELL_CANCEL_ERROR.getName());
            }
            transaction.setVersion(temp.getVersion() + 1);
            transaction.setTradeId(temp.getTradeId());
            transactionMapper.insert(transaction);
            transaction = transactionMapper.queryTransactionByTransactionId(transaction);
        }catch (Exception e){
            throw new RequestException(400, e.getMessage());
        }finally {
            lock.unlock();
        }
        return transaction;
    }


    @Override
    public List<Transaction> queryTransactionList(Transaction transaction) {
        return transactionMapper.queryTransactionList(transaction);
    }

    @Autowired
    private TransactionMapper transactionMapper;
}
